using BW.WMS.WareHouseManage.Dtos;
using BW.WMS.WareHouseManage.IServices;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;

namespace BW.WMS.WareHouseManage.Services
{
    /// <summary>
    /// 库区服务实现
    /// </summary>
    public class ZoneAppService : ApplicationService, IZoneAppService
    {
        private readonly IRepository<Zone, Guid> _zoneRepository;
        private readonly IRepository<Warehouse, Guid> _warehouseRepository;

        public ZoneAppService(
            IRepository<Zone, Guid> zoneRepository,
            IRepository<Warehouse, Guid> warehouseRepository)
        {
            _zoneRepository = zoneRepository;
            _warehouseRepository = warehouseRepository;
        }

        /// <summary>
        /// 批量删除库区
        /// </summary>
        public async Task<BatchDeleteResultDto> BatchDeleteAsync(List<Guid> ids)
        {
            // 初始化结果对象
            var result = new BatchDeleteResultDto();

            if (ids == null || !ids.Any())
            {
                return result; // 无需删除任何内容
            }
            foreach (var id in ids)
            {
                // 检查库区是否存在
                var zone = await _zoneRepository.GetAsync(id);

                // 检查库区是否有关联数据（如库位）
                bool hasRelatedData = await CheckZoneHasRelatedData(id);
                if (hasRelatedData)
                {
                    // 记录失败信息
                    result.FailedCount++;
                    result.Errors.Add(new BatchDeleteErrorItem
                    {
                        Id = id,
                        Error = "库区存在关联的库位数据，无法删除"
                    });
                    continue;
                }

                // 删除库区
                await _zoneRepository.DeleteAsync(id);
                result.SuccessCount++;
            }
            return result;
        }

        /// <summary>
        /// 检查库区是否有关联数据
        /// </summary>
        private async Task<bool> CheckZoneHasRelatedData(Guid zoneId)
        {
            // TODO: 实际项目中，需要检查库区是否有关联的库位或其他数据
            // 示例代码，假设有一个LocationRepository可以查询库位
            // 需要根据实际项目结构调整

            // var locationRepository = LazyServiceProvider.LazyGetRequiredService<IRepository<Location, Guid>>();
            // return await locationRepository.AnyAsync(l => l.ZoneId == zoneId);

            // 暂时返回false，表示没有关联数据
            return false;
        }

        /// <summary>
        /// 添加库区
        /// </summary>
        public async Task<ZoneDto> CreateAsync(AddZoneDto input)
        {
            try
            {
                // 检查仓库是否存在
                var warehouse = await _warehouseRepository.GetAsync(input.WarehouseId);
                if (warehouse == null)
                {
                    throw new UserFriendlyException("所选仓库不存在");
                }

                // 检查库区名称是否已存在
                var existingZone = await _zoneRepository.FirstOrDefaultAsync(z =>
                    z.Name == input.Name && z.WarehouseId == input.WarehouseId);

                if (existingZone != null)
                {
                    throw new UserFriendlyException("该仓库下已存在相同名称的库区");
                }

                var zone = ObjectMapper.Map<AddZoneDto, Zone>(input);
                //编号等于 WareHouse + 当前时间的年月日 +从0000开始递增的数字
                zone.Code = "Zone" + DateTime.Now.ToString("yyyyMMdd") + (await _zoneRepository.GetCountAsync()).ToString("D4");

                await _zoneRepository.InsertAsync(zone);
                return ObjectMapper.Map<Zone, ZoneDto>(zone);
            }
            catch (Exception ex)
            {

                // 记录详细错误
                Logger.LogError($"创建库区失败: {ex.Message}, {ex.StackTrace}");
                throw new UserFriendlyException("创建库区失败，详细信息：" + ex.Message);
            }
            
        }

        /// <summary>
        /// 删除库区
        /// </summary>
        public async Task DeleteAsync(Guid id)
        {
            // 检查库区是否存在
            var zone = await _zoneRepository.GetAsync(id);
            if (zone == null)
            {
                throw new UserFriendlyException("库区不存在");
            }

            // TODO: 检查库区是否有关联的库位或库存
            // 如果有关联的库位或库存，则不允许删除
            
            // 删除库区
            await _zoneRepository.DeleteAsync(id);
        }

        /// <summary>
        /// 获取库区信息
        /// </summary>
        public async Task<ZoneDto> GetAsync(Guid id)
        {
            // 获取库区，包括仓库信息
            var query = await _zoneRepository.WithDetailsAsync(z => z.Warehouse);
            var zone = await query.FirstOrDefaultAsync(z => z.Id == id);
            
            if (zone == null)
            {
                throw new UserFriendlyException("库区不存在");
            }

            // 转换为DTO并返回
            var zoneDto = ObjectMapper.Map<Zone, ZoneDto>(zone);
            zoneDto.WarehouseName = zone.Warehouse?.Name;
            
            return zoneDto;
        }

        /// <summary>
        /// 获取库区列表
        /// </summary>
        public async Task<PagedResultDto<ZoneDto>> GetPagedListAsync(PagedZoneRequestDto input)
        {
            // 构建查询
            var query = await _zoneRepository.WithDetailsAsync(z => z.Warehouse);

            // 应用过滤条件
            if (!string.IsNullOrWhiteSpace(input.Name))
            {
                query = query.Where(z => z.Name.Contains(input.Name));
            }
            
            if (input.ZoneType.HasValue)
            {
                query = query.Where(z => z.ZoneType == input.ZoneType.Value);
            }
            
            if (input.WarehouseId.HasValue)
            {
                query = query.Where(z => z.WarehouseId == input.WarehouseId.Value);
            }

            // 获取总数
            var totalCount = await query.CountAsync();

            // 应用排序和分页
            var ordering = !string.IsNullOrWhiteSpace(input.Sorting)
                ? query.OrderByDescending(x=>x.Name)
                : query.OrderByDescending(z => z.Code);

            var zones = await ordering
                .Skip(input.SkipCount)
                .Take(input.MaxResultCount)
                .ToListAsync();

            // 转换为DTO
            var zoneDtos = zones.Select(z => 
            {
                var dto = ObjectMapper.Map<Zone, ZoneDto>(z);
                dto.WarehouseName = z.Warehouse?.Name;
                return dto;
            }).ToList();

            return new PagedResultDto<ZoneDto>(totalCount, zoneDtos);
        }

        /// <summary>
        /// 根据仓库ID获取库区列表
        /// </summary>
        public async Task<List<ZoneDto>> GetZonesByWarehouseIdAsync(Guid warehouseId)
        {
            // 检查仓库是否存在
            var warehouse = await _warehouseRepository.GetAsync(warehouseId);
            if (warehouse == null)
            {
                throw new UserFriendlyException("仓库不存在");
            }

            // 获取库区列表
            var zones = await _zoneRepository.GetListAsync(z => z.WarehouseId == warehouseId);

            // 转换为DTO
            var zoneDtos = zones.Select(z => 
            {
                var dto = ObjectMapper.Map<Zone, ZoneDto>(z);
                dto.WarehouseName = warehouse.Name;
                return dto;
            }).ToList();

            return zoneDtos;
        }

        /// <summary>
        /// 修改库区信息
        /// </summary>
        public async Task<ZoneDto> UpdateAsync(Guid id, UpdateZoneDto input)
        {
            // 检查库区是否存在
            var zone = await _zoneRepository.GetAsync(id);
            if (zone == null)
            {
                throw new UserFriendlyException("库区不存在");
            }

            // 如果修改了所属仓库，检查新仓库是否存在
            if (zone.WarehouseId != input.WarehouseId)
            {
                var newWarehouse = await _warehouseRepository.GetAsync(input.WarehouseId);
                if (newWarehouse == null)
                {
                    throw new UserFriendlyException("所选仓库不存在");
                }
            }

            // 检查库区名称在新仓库下是否已存在（排除自身）
            var existingZone = await _zoneRepository.FirstOrDefaultAsync(z =>
                z.Id != id &&
                z.Name == input.Name &&
                z.WarehouseId == input.WarehouseId);

            if (existingZone != null)
            {
                throw new UserFriendlyException("该仓库下已存在相同名称的库区");
            }

            // 更新库区属性
            zone.WarehouseId = input.WarehouseId;
            zone.Name = input.Name;
            zone.ZoneType = input.ZoneType;
            zone.Status = input.Status;
            zone.Description = input.Description;
            zone.Area = input.Area;

            // 保存更新
            await _zoneRepository.UpdateAsync(zone);

            // 查询关联的仓库名称
            var warehouse = await _warehouseRepository.GetAsync(input.WarehouseId);

            // 转换为DTO并返回
            var zoneDto = ObjectMapper.Map<Zone, ZoneDto>(zone);
            zoneDto.WarehouseName = warehouse.Name;

            return zoneDto;
        }
    }
} 